import { getCurrentInstance, onMounted, onUpdated, ref, Ref } from '@vue/composition-api';

export const useUview = () => {
  return uni.$u;
};

export const useDomRefs = () => {
  const current = getCurrentInstance();
  return <T = any>(refs: any, dom: string) => {
    // return current && ((current as ComponentInternalInstance)).refs[dom].$vm as T);
    if (current) {
      return current.refs?.[dom] as T;
    }
    return refs[dom].$vm as T;
  };
};

import Vue, { ComponentOptions } from 'vue';
// import { CombinedVueInstance } from 'vue/types/vue';
import { CombinedVueInstance } from 'vue/types/vue';
type VueInstance = Vue extends { $refs: { [key: string]: infer R } } ? R : never;
type CombinedVueInstanceFromOptions<Options extends ComponentOptions<Vue>> = Options extends ComponentOptions<
  infer Vue,
  infer Data,
  infer Methods,
  infer Computed,
  {},
  infer Props
>
  ? CombinedVueInstance<Vue, Data, Methods, Computed, Props>
  : never;

/**
 * @description 接收一个字符串返回对应的ref名称的组件实例
 * @example
 * setup() {
 *     //如果是class组件
 *     const input = useVueRef<Input>('refName')
 *     //如果是选项式组件
 *     const input = useVueRef<InstanceType<typeof Input>>('refName')
 *
 *     onMounted(() => input.value?.focus())
 * }
 * */
export function useVueRef<
  Instance extends ComponentOptions<Vue> | ComponentOptions<Vue>[] | VueInstance = VueInstance,
  VueRef = Instance extends VueInstance
    ? Instance
    : Instance extends ComponentOptions<Vue>[]
    ? CombinedVueInstanceFromOptions<Instance[number]>[]
    : Instance extends ComponentOptions<Vue>
    ? CombinedVueInstanceFromOptions<Instance>
    : never
>(refName: string): Ref<VueRef | undefined> {
  const $vm = getCurrentInstance()?.proxy;
  const vueRef = ref<VueRef | undefined>();
  if ($vm) {
    const refreshRef = () => {
      vueRef.value = $vm.$refs[refName] as unknown as VueRef | undefined;
    };
    onMounted(refreshRef);
    onUpdated(refreshRef);
  }
  return vueRef;
}
